package controllers

import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/beego/beego/v2/core/logs"
	"github.com/beego/beego/v2/server/web"

	"supershare/backend/middleware"
	"supershare/backend/models"
)

// MiniprogramConfigController 小程序配置控制器
type MiniprogramConfigController struct {
	web.Controller
}

// Get 获取小程序配置
// @Title Get
// @Description 获取小程序配置
// @Success 200 {object} models.Response
// @Failure 500 服务器错误
// @router / [get]
func (c *MiniprogramConfigController) Get() {
	admin, _ := middleware.GetCurrentAdmin(c.Ctx)
	if admin == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "参数错误",
			"error":   "没有权限",
		}
		c.ServeJSON()
		return
	}
	config, err := models.GetMiniprogramConfigByFranchiseId(admin.FranchiseId)
	if err != nil {
		logs.Error("获取小程序配置失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "获取小程序配置失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}
	config.FranchiseId = admin.FranchiseId
	c.Data["json"] = map[string]interface{}{
		"success": true,
		"message": "获取小程序配置成功",
		"data":    config,
	}
	c.ServeJSON()
}

// Put 更新小程序配置
// @Title Put
// @Description 更新小程序配置
// @Param body body models.MiniprogramConfig true "小程序配置信息"
// @Success 200 {object} models.Response
// @Failure 500 服务器错误
// @router / [put]
func (c *MiniprogramConfigController) Put() {
	// 使用原始模型解析请求参数，保持兼容性
	var config models.MiniprogramConfig
	err := json.Unmarshal(c.Ctx.Input.RequestBody, &config)
	if err != nil {
		logs.Error("解析请求参数失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "参数错误",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}
	admin, _ := middleware.GetCurrentAdmin(c.Ctx)
	if admin == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "参数错误",
			"error":   "没有权限",
		}
		c.ServeJSON()
		return
	}
	config.UpdatedBy = admin.Username
	config.FranchiseId = admin.FranchiseId
	config.BeforeUpdate()
	// 更新小程序配置，只更新非空字段
	err = models.UpdateMiniprogramConfig(&config)
	if err != nil {
		logs.Error("更新小程序配置失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "更新小程序配置失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}

	c.Data["json"] = map[string]interface{}{
		"success": true,
		"message": "更新小程序配置成功",
	}
	c.ServeJSON()
}

// UploadCert 上传支付证书文件
// @Title UploadCert
// @Description 上传支付证书文件(cert_file或key_file)
// @Param file formData file true "证书文件"
// @Param type formData string true "文件类型(cert_file或key_file)"
// @Success 200 {object} models.Response
// @Failure 500 服务器错误
// @router /upload_cert [post]
func (c *MiniprogramConfigController) UploadCert() {
	admin, _ := middleware.GetCurrentAdmin(c.Ctx)
	if admin == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "参数错误",
			"error":   "没有权限",
		}
		c.ServeJSON()
		return
	}

	// 获取文件类型参数
	fileType := c.GetString("type")
	if fileType != "cert_file" && fileType != "key_file" {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "参数错误",
			"error":   "文件类型必须是cert_file或key_file",
		}
		c.ServeJSON()
		return
	}

	// 获取上传的文件
	file, header, err := c.GetFile("file")
	if err != nil {
		logs.Error("获取上传文件失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "获取上传文件失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}
	defer file.Close()

	// 验证文件扩展名
	allowedExts := []string{".pem", ".crt", ".key", ".p12", ".pfx"}
	ext := strings.ToLower(filepath.Ext(header.Filename))
	isValidExt := false
	for _, allowedExt := range allowedExts {
		if ext == allowedExt {
			isValidExt = true
			break
		}
	}
	if !isValidExt {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "文件格式不支持",
			"error":   "只支持.pem, .crt, .key, .p12, .pfx格式的证书文件",
		}
		c.ServeJSON()
		return
	}

	// 验证文件大小 (限制为5MB)
	if header.Size > 5*1024*1024 {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "文件过大",
			"error":   "证书文件大小不能超过5MB",
		}
		c.ServeJSON()
		return
	}

	// 创建上传目录
	uploadDir := "static/uploads/certs"
	if err := os.MkdirAll(uploadDir, 0755); err != nil {
		logs.Error("创建上传目录失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "创建上传目录失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 生成文件名
	timestamp := time.Now().Format("20060102150405")
	filename := fmt.Sprintf("%s_%d_%s_%s%s", fileType, admin.FranchiseId, timestamp, strings.TrimSuffix(header.Filename, ext), ext)
	filePath := filepath.Join(uploadDir, filename)

	// 保存文件
	dst, err := os.Create(filePath)
	if err != nil {
		logs.Error("创建文件失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "保存文件失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}
	defer dst.Close()

	// 复制文件内容
	if _, err := io.Copy(dst, file); err != nil {
		logs.Error("保存文件内容失败: %v", err)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "保存文件失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 返回文件路径
	fileUrl := "/" + strings.ReplaceAll(filePath, "\\", "/")

	// 更新数据库中的证书文件路径
	config, _ := models.GetMiniprogramConfigByFranchiseId(admin.FranchiseId)
	if config == nil {
		logs.Error("获取小程序配置失败")
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "获取小程序配置失败",
			"error":   "获取小程序配置失败",
		}
		c.ServeJSON()
		return
	}
	// 根据文件类型设置对应字段
	if fileType == "cert_file" {
		config.CertFile = fileUrl
	} else if fileType == "key_file" {
		config.KeyFile = fileUrl
	}

	config.BeforeUpdate()

	// 更新小程序配置
	err = models.UpdateMiniprogramConfig(config)
	if err != nil {
		logs.Error("更新证书文件路径失败: %v", err)
		// 删除已上传的文件
		os.Remove(filePath)
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "更新证书文件路径失败",
			"error":   err.Error(),
		}
		c.ServeJSON()
		return
	}

	c.Data["json"] = map[string]interface{}{
		"success": true,
		"message": "证书文件上传成功",
		"data": map[string]interface{}{
			"url":      fileUrl,
			"filename": filename,
			"type":     fileType,
			"size":     header.Size,
		},
	}
	c.ServeJSON()
}
